﻿﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;

namespace ReadXml
{

 
    class RecogClass
    {
        public List<List<List<double>>> preprocess(List<List<List<double>>> testarray)
        {
            for (int i = 0; i < testarray.Count; i++)
            {
                if (testarray[i][0].Count < 100)
                {
                    int count = 100 - testarray[i][0].Count;
                    for (int j = 0; j < 3; j++)
                    {
                        for (int m = 0; m < 2 * count; m++)
                        {
                            int countone = 100 - testarray[i][j].Count;
                            int counttwo = countone - 1;
                            if (m >= counttwo)
                            {
                                for (int k = 0; k < countone; k++)
                                {
                                    testarray[i][j].Add(0);
                                }
                            }
                            else if (m < counttwo)
                            {
                                double addValue = (testarray[i][j][m + 1] - testarray[i][j][m]) / 2.0;
                                testarray[i][j].Insert(m + 1, addValue);
                                m++;
                            }
                        }
                    }
                }
                else if (testarray[i][0].Count > 100)
                {
                    int count = testarray[i][0].Count - 100;
                    for (int j = 0; j < 3; j++)
                    {
                        for (int m = 0; m < 2 * count; m++)
                        {
                            int countone = testarray[i][j].Count - 100;
                            int counttwo = countone - 1;
                            if (m >= counttwo)
                            {
                                for (int k = 0; k < countone; k++)
                                {
                                    testarray[i][j].RemoveAt(0);
                                }
                            }
                            else if (m < counttwo)
                            {
                                double addValue = (testarray[i][j][m + 1] - testarray[i][j][m]) / 2.0;
                                testarray[i][j].RemoveAt(m + 1);
                                m++;
                            }
                        }
                    }
                }

            }
            return testarray;
        }
        public void recogClass()
        {
            /***** 获取训练集和测试集 *****/
            List<List<List<double>>> trainarray = new List<List<List<double>>>();
            List<List<List<double>>> testarray = new List<List<List<double>>>();
            List<string> trainclassarray = new List<string>();
            List<string> testclassarray = new List<string>();
            List<string> classnames = new List<string>();
            (new TrainData()).trainData(ref trainarray, ref testarray, ref trainclassarray, ref classnames, ref testclassarray);

            /***** 轨迹预处理，插值加点删点规整到100个点的长度 *****/
            //testarray = preprocess(testarray);
           // trainarray = preprocess(trainarray);

            /***** 产生随机数组 *****/
            int Length = 100; //这个怎么取啊？

            //int lambda = gLength / 3;
            int lambda = 20;    //参数K暂时取20
            Random random = new Random();
            int[] tarray = new int[lambda];
            for (int i = 0; i < tarray.Length; i++)
            {
                int x = random.Next(4, Length); //>=4且<Length                
                for (int j = 0; j < i; j++)
                {
                    if (x == tarray[j])
                    {
                        x = random.Next(4, Length); //抽取大于等于4的点 且<Length
                        j = -1;
                    }
                }
                tarray[i] = x;
                //Console.WriteLine(tarray[i]);
            }



            /***** 获取特征矩阵 *****/
            var trainEigen = new GetEigenMatrix().getEigenMatrix(trainarray,  tarray,lambda);
            var testEigen = new GetEigenMatrix().getEigenMatrix(testarray, tarray,lambda);

            /***** test *****/
            double []difftest = new double[4];
            double[] difftest1 = new double[4];
            double[] difftest2 = new double[4];
            for (int m = 0; m < 4; m++)
            {
                for (int i = 0; i < testEigen[m].Count; i++)
                {
                    for (int j = 0; j < testEigen[m][i].Count; j++)
                    {
                        difftest[m] += trainEigen[m][i][j]-testEigen[34][i][j]  ;
                        difftest1[m] += trainEigen[m+34][i][j]-testEigen[34][i][j]  ;
                        //difftest2[m] += trainEigen[m][i][j] - testEigen[0][i][j];
                    }
                }
            }

            /***** 开始分类识别 *****/
            
            List<string> resultArray = new List<string>();
            //double distance = 0;        
            /***** 采用DTW优化，计算测试集与训练集之间的差异 *****/
            for (int i = 0; i < testEigen.Count; i++) //181个测试样本遍历
            {
                List<double> knn = new List<double>();
                for (int j = 0; j < trainEigen.Count; j++) //每一个测试样本去与281个训练样本比对
                {

                    double[,] routMatrix = new double[testEigen[i].Count, trainEigen[j].Count];
                    //List<List<double>> variMatrix = new List<List<double>>();   
                    double[,] variMatrix = new double[testEigen[i].Count, trainEigen[j].Count]; //直接用二维数组了。
                    for (int k = 0; k < testEigen[i].Count; k++) //计算DTW预处理矩阵
                    {
                       // List<double> list = new List<double>();
                        for (int m = 0; m < trainEigen[j].Count; m++)
                        {
                            double diff = 0;
                            if ((m > 19 && k > 19) || (m <= 19 && m == k))
                            {
                                for (int n = 0; n < trainEigen[j][m].Count; n++)
                                {
                                    diff += Math.Sqrt(Math.Pow((testEigen[i][k][n] - trainEigen[j][m][n]), 2)); //有问题 
                                }
                                variMatrix[k, m] = diff;
                            }
                            //variMatrix[k,m]=0;
                            //把前面10个点空出来
                           // list.Add(diff);
                        }
                       // variMatrix.Add(list);
                    }
                    for (int k = 0; k < testEigen[i].Count; k++)
                    {
                        for (int m = 0; m < trainEigen[j].Count; m++)
                        {
                            if (m > 19 && k>19) //相当于把DTW矩阵抬高了。
                            {
                                if (k == 20 && m > 20) //边界也应该相应提高。
                                {
                                    routMatrix[k, m] = routMatrix[k, m - 1] + variMatrix[k, m];
                                }
                                else if (m == 20 && k > 20)
                                {
                                    routMatrix[k, m] = routMatrix[k - 1, m] + variMatrix[k, m];
                                }
                                else if (k > 20 && m > 20)
                                {
                                    routMatrix[k, m] = Math.Min(Math.Min(routMatrix[k - 1, m], routMatrix[k, m - 1]), routMatrix[k - 1, m - 1]) + variMatrix[k, m];
                                }
                            }
                            else if (m <= 19 && m == k)
                            {
                                    routMatrix[testEigen[i].Count-1, trainEigen[j].Count-1] +=variMatrix[k,m]; //为什么第一次计算routMatrix最后的值才40多，是不是小了点。
                            }
                        }
                    }
                     
                    knn.Add(routMatrix[testEigen[i].Count-1, trainEigen[j].Count-1]); //记住减1，这种小细节很重要啊。会导致超出索引的错误。
                }
                double min = knn.Min();
                int minindex = knn.IndexOf(knn.Min());
                string minclass = trainclassarray[minindex];
                resultArray.Add(minclass);
                Console.WriteLine(resultArray[i]);
            }           
           
            double  classcount= 0.00;
            for (int i = 0; i < resultArray.Count; i++)
            {
                if (resultArray[i] == testclassarray[i])
                {
                    classcount++;
                }
            }
            Console.WriteLine(classcount/resultArray.Count);
        }
    }

            
           
}       

